package com.heima.service.impl;

import com.google.common.util.concurrent.RateLimiter;
import com.heima.component.RedisComponent;
import com.heima.entity.config.AppConfig;
import com.heima.entity.constants.Constants;
import com.heima.entity.dto.SessionWebUserDto;
import com.heima.entity.dto.UploadResultDto;
import com.heima.entity.dto.UserSpaceDto;
import com.heima.entity.enums.*;
import com.heima.entity.po.FileInfo;
import com.heima.entity.po.FileTreeNode;
import com.heima.entity.po.UserInfo;
import com.heima.entity.query.FileInfoQuery;
import com.heima.entity.query.SimplePage;
import com.heima.entity.query.UserInfoQuery;
import com.heima.entity.vo.PaginationResultVO;
import com.heima.exception.BusinessException;
import com.heima.mapper.FileInfoMapper;
import com.heima.mapper.UserInfoMapper;
import com.heima.service.FileInfoService;
import com.heima.utils.DateUtil;
import com.heima.utils.ProcessUtils;
import com.heima.utils.ScaleFilter;
import com.heima.utils.StringTools;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 文件信息 业务接口实现
 */
@Service("fileInfoService")
public class FileInfoServiceImpl implements FileInfoService {

    private static final Logger logger = LoggerFactory.getLogger(FileInfoServiceImpl.class);

    private static final HashMap<String,FileTreeNode> treeMap = new HashMap<>();
    @Resource
    @Lazy
    private FileInfoServiceImpl fileInfoService;

    @Resource
    private AppConfig appConfig;


    @Resource
    private FileInfoMapper<FileInfo, FileInfoQuery> fileInfoMapper;

    @Resource
    private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;

    @Resource
    private RedisComponent redisComponent;


    //每次1M
    public static final double bytesLimit = 1024*1000;
    /**
     * 根据条件查询列表
     */
    @Override
    public List<FileInfo> findListByParam(FileInfoQuery param) {
        return this.fileInfoMapper.selectList(param);
    }

    /**
     * 根据条件查询列表
     */
    @Override
    public Integer findCountByParam(FileInfoQuery param) {
        return this.fileInfoMapper.selectCount(param);
    }

    /**
     * 分页查询方法
     */
    @Override
    public PaginationResultVO<FileInfo> findListByPage(FileInfoQuery param) {
        int count = this.findCountByParam(param);
        int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

        SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
        param.setSimplePage(page);
        List<FileInfo> list = this.findListByParam(param);
        PaginationResultVO<FileInfo> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
        return result;
    }

    /**
     * 新增
     */
    @Override
    public Integer add(FileInfo bean) {
        return this.fileInfoMapper.insert(bean);
    }

    /**
     * 批量新增
     */
    @Override
    public Integer addBatch(List<FileInfo> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.fileInfoMapper.insertBatch(listBean);
    }

    /**
     * 批量新增或者修改
     */
    @Override
    public Integer addOrUpdateBatch(List<FileInfo> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.fileInfoMapper.insertOrUpdateBatch(listBean);
    }

    /**
     * 根据FileIdAndUserId获取对象
     */
    @Override
    public FileInfo getFileInfoByFileIdAndUserId(String fileId, String userId) {
        return this.fileInfoMapper.selectByFileIdAndUserId(fileId, userId);
    }

    /**
     * 根据FileIdAndUserId修改
     */
    @Override
    public Integer updateFileInfoByFileIdAndUserId(FileInfo bean, String fileId, String userId) {
        return this.fileInfoMapper.updateByFileIdAndUserId(bean, fileId, userId);
    }

    /**
     * 根据FileIdAndUserId删除
     */
    @Override
    public Integer deleteFileInfoByFileIdAndUserId(String fileId, String userId) {
        return this.fileInfoMapper.deleteByFileIdAndUserId(fileId, userId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public UploadResultDto uploadFile(SessionWebUserDto userDto, String fileId, MultipartFile file, String fileName, String filePid, String fileMd5, Integer chunkIndex, Integer chunks) {
        UploadResultDto uploadResultDto = new UploadResultDto();
        Boolean uploadSuccess = true;
        File tempFileFolde = null;
        try {

        if (StringTools.isEmpty(fileId)) {
            fileId = StringTools.getRandomString(Constants.LENGTH_10);
        }
        uploadResultDto.setFileId(fileId);
        Date curDate = new Date();
        UserSpaceDto userSpaceUse = redisComponent.getUserSpaceUse(userDto.getUserId());

        if (chunkIndex == 0) {
            FileInfoQuery fileInfoQuery = new FileInfoQuery();
            fileInfoQuery.setFileMd5(fileMd5);
            fileInfoQuery.setSimplePage(new SimplePage(0, 1));
            fileInfoQuery.setStatus(FileStatusEnums.USING.getStatus());
            List<FileInfo> fileInfos = fileInfoMapper.selectList(fileInfoQuery);

            //秒传
            if (!fileInfos.isEmpty()) {
                FileInfo fileInfo = fileInfos.get(0);
                //判断文件大小
                if (fileInfo.getFileSize() + userSpaceUse.getUseSpace() > userSpaceUse.getTotalSpace()) {
                    throw new BusinessException(ResponseCodeEnum.CODE_904);
                }
                fileInfo.setFileId(fileId);
                fileInfo.setFilePid(filePid);
                fileInfo.setUserId(userDto.getUserId());
                fileInfo.setFileMd5(null);
                fileInfo.setCreateTime(curDate);
                fileInfo.setLastUpdateTime(curDate);
                fileInfo.setStatus(FileStatusEnums.USING.getStatus());
                fileInfo.setDelFlag(FileDelFlagEnums.USING.getFlag());
                fileInfo.setFileMd5(fileMd5);
                //文件重命名
                fileName = autoRename(filePid, userDto.getUserId(), fileName);
                fileInfo.setFileName(fileName);
                uploadResultDto.setStatus(UploadStatusEnums.UPLOAD_SECONDS.getCode());
                this.fileInfoMapper.insert(fileInfo);
                //更新用户使用空间
                updateUserSpace(userDto, fileInfo.getFileSize());
                return uploadResultDto;
            }
        }
            //判断磁盘空间
            Long currentTempSize = redisComponent.getFileTempSize(userDto.getUserId(), fileId);
            if (file.getSize() + currentTempSize + userSpaceUse.getUseSpace() > userSpaceUse.getTotalSpace()) {
                throw new BusinessException(ResponseCodeEnum.CODE_904);
            }
            //暂存临时目录
            String tempFolderName = appConfig.getProjectFolder() + Constants.FILE_FOLDER_TEMP;
            String currentUserFolderName = userDto.getUserId() + fileId;

            tempFileFolde = new File(tempFolderName + currentUserFolderName);
            if (!tempFileFolde.exists()) {
                tempFileFolde.mkdirs();
            }
            //分片上传

            File newFile = new File(tempFileFolde.getPath() + "/" + chunkIndex);
//            file.transferTo(newFile);
            saveToTemp(file,newFile);
            //保存临时大小
            redisComponent.saveFileTempSize(userDto.getUserId(),fileId,file.getSize());
            if(chunkIndex < chunks-1){
                uploadResultDto.setStatus(UploadStatusEnums.UPLOADING.getCode());

                return uploadResultDto;
            }

            //最后一个分片
            String month = DateUtil.format(new Date(),DateTimePatternEnum.YYYYMM.getPattern());
            String fileSuffix = StringTools.getFileSuffix(fileName);
            //真实文件名
            String realFileName = currentUserFolderName + fileSuffix;
            FileTypeEnums fileTypeEnums = FileTypeEnums.getFileTypeBySuffix(fileSuffix);
            //自动重命名
            fileName = autoRename(filePid,userDto.getUserId(),fileName);

            FileInfo info = new FileInfo();
            info.setFileId(fileId);
            info.setUserId(userDto.getUserId());
            info.setFileMd5(fileMd5);
            info.setFileName(fileName);
            info.setFilePath(month + "/" + realFileName);
            info.setFilePid(filePid);
            info.setCreateTime(curDate);
            info.setLastUpdateTime(curDate);
            info.setFileCategory(fileTypeEnums.getCategory().getCategory());
            info.setFileType(fileTypeEnums.getType());
            info.setStatus(FileStatusEnums.TRANSFER.getStatus());
            info.setFolderType(FileFolderTypeEnums.FILE.getType());
            info.setDelFlag(FileDelFlagEnums.USING.getFlag());
            info.setFileSize(redisComponent.getFileTempSize(userDto.getUserId(),fileId));
            this.fileInfoMapper.insert(info);

            Long totalSize = redisComponent.getFileTempSize(userDto.getUserId(),fileId);
            updateUserSpace(userDto,totalSize);
            uploadResultDto.setStatus(UploadStatusEnums.UPLOAD_FINISH.getCode());

            //info.getFileId()查不到文件 等事务提交结束后
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    fileInfoService.transferFile(info.getFileId(),userDto);
                }
            });

        }
        catch (BusinessException e){
            logger.error("文件上传失败",e);
            uploadSuccess = false;
            throw new BusinessException("文件上传失败");
        }
        catch (Exception e) {
            logger.error("文件上传失败",e);
            uploadSuccess = false;


        }finally {
            //如果上传失败，清除临时目录
            if (tempFileFolde != null && !uploadSuccess) {
                try {
                    FileUtils.deleteDirectory(tempFileFolde);
                } catch (IOException e) {
                    logger.error("删除临时目录失败");
                }
            }
        }
        return uploadResultDto;
    }

    private void saveToTemp(MultipartFile file,File newFile){
        RateLimiter rateLimiter = RateLimiter.create(bytesLimit);

//        FileInputStream in = null;
//        FileOutputStream fos = null;
        try {
            byte[] bytes = new byte[4096];
            InputStream in = file.getInputStream();
            FileOutputStream fos = new FileOutputStream(newFile);
            int b;
            while ((b = in.read(bytes)) != -1){
                rateLimiter.acquire(b);
                fos.write(bytes,0,b);
            }

            fos.close();
            in.close();

        } catch (FileNotFoundException e) {
            logger.error("临时文件存储错误!");
            throw new RuntimeException(e);
        } catch (IOException e) {
            logger.error("临时文件存储错误!");
            throw new RuntimeException(e);
        }


    }
    @Override
    public FileInfo newFolder(String filePid, String fileName, String userId) {
        checkFileName(filePid,userId,fileName,FileFolderTypeEnums.FOLDER.getType());
        Date curDate = new Date();
        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileId(StringTools.getRandomString(Constants.LENGTH_10));
        fileInfo.setFilePid(filePid);
        fileInfo.setFileName(fileName);
        fileInfo.setUserId(userId);
        fileInfo.setFolderType(FileFolderTypeEnums.FOLDER.getType());
        fileInfo.setCreateTime(curDate);
        fileInfo.setStatus(FileStatusEnums.USING.getStatus());
        fileInfo.setDelFlag(FileDelFlagEnums.USING.getFlag());
        fileInfo.setLastUpdateTime(new Date());
        fileInfoMapper.insert(fileInfo);
        return fileInfo;
    }
    private void checkFileName(String filePid,String userId,String fileName,Integer folderType){
        FileInfoQuery fileInfoQuery = new FileInfoQuery();
        fileInfoQuery.setFolderType(folderType);
        fileInfoQuery.setFileName(fileName);
        fileInfoQuery.setFilePid(filePid);
        fileInfoQuery.setUserId(userId);
        fileInfoQuery.setDelFlag(FileDelFlagEnums.USING.getFlag());
        Integer i = fileInfoMapper.selectCount(fileInfoQuery);
        if (i > 0){
            throw new BusinessException("此目录下存在同名文件，请修改名称");
        }
    }

    @Override
    public FileInfo[] getFolderInfo(SessionWebUserDto webUserDto, String path) {
        FileInfo[] fileInfos = fileInfoMapper.getFileInfoByPidAnduserId(webUserDto.getUserId(),path);


        return fileInfos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileInfo rename(String userId, String fileId, String fileName) {
        FileInfo fileInfo = fileInfoMapper.selectByFileIdAndUserId(fileId, userId);
        if (fileInfo == null){
            throw new BusinessException("文件不存在");
        }
//        int i = fileInfo.getFileName().lastIndexOf(".");
//        String suffix = fileInfo.getFileName().substring(i);

        checkFileName(fileInfo.getFilePid(),userId,fileName,fileInfo.getFolderType());
        if (FileFolderTypeEnums.FILE.getType().equals(fileInfo.getFolderType())) {
            fileName = fileName + StringTools.getFileSuffix(fileInfo.getFileName());
        }
        Date curDate = new Date();
        fileInfo.setFileName(fileName);
        fileInfo.setLastUpdateTime(curDate);
        fileInfoMapper.updateByFileIdAndUserId(fileInfo,fileId,userId);

        FileInfoQuery fileInfoQuery = new FileInfoQuery();
        fileInfoQuery.setFilePid(fileInfo.getFilePid());
        fileInfoQuery.setUserId(userId);
        fileInfoQuery.setFileName(fileName);

        Integer i = fileInfoMapper.selectCount(fileInfoQuery);
        if (i > 1){
            throw new BusinessException("文件名"+ fileName + "已存在");
        }
        return fileInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeFileFolder(String userId, String fileIds, String filePid) {
        Long fileSize = 0L;
        String[] fileId = fileIds.split(",");

        for (String s : fileId) {
            if (s.equals(filePid)){
                throw new BusinessException(ResponseCodeEnum.CODE_600);
            }

        }
        if (!Constants.ZERO_STR.equals(filePid)){
            FileInfo fileInfo = getFileInfoByFileIdAndUserId(filePid, userId);
            if (fileInfo == null || !FileDelFlagEnums.USING.getFlag().equals(fileInfo.getDelFlag())){
                throw new BusinessException(ResponseCodeEnum.CODE_600);
            }
        }

        //查询移动的文件夹中存在的文件
        FileInfoQuery query = new FileInfoQuery();
        query.setUserId(userId);
        query.setFilePid(filePid);
        List<FileInfo> fileInfoList = fileInfoService.findListByParam(query);
        Map<String,FileInfo> fileInfoMap = fileInfoList.stream().collect(Collectors.toMap(FileInfo::getFileName,Function.identity(),(data1,data2)->data2));

        //查询选中的文件
        query = new FileInfoQuery();
        query.setFileIdArray(fileId);
        query.setUserId(userId);
        List<FileInfo> fileInfos = findListByParam(query);

        //如果选中的文件与移动的文件夹中的文件出现重名
        for (FileInfo fileInfo : fileInfos) {
            fileSize += fileInfo.getFileSize();
            FileInfo fileInfo1 = fileInfoMap.get(fileInfo.getFileName());
            FileInfo updateInfo = new FileInfo();
            if (fileInfo1 != null){
                String fileName = StringTools.rename(fileInfo.getFileName());
                updateInfo.setFileName(fileName);
            }
            updateInfo.setFilePid(filePid);

            fileInfoMapper.updateByFileIdAndUserId(updateInfo,fileInfo.getFileId(),userId);
        }
        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileSize(fileSize);

        fileInfoMapper.updateByFileIdAndUserId(fileInfo,filePid,userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delFile(String userId, String fileIds) {
        String[] fileIdArray = fileIds.split(",");

        FileInfoQuery fileInfoQuery = new FileInfoQuery();
        fileInfoQuery.setFileIdArray(fileIdArray);
        fileInfoQuery.setUserId(userId);
        fileInfoQuery.setDelFlag(FileDelFlagEnums.USING.getFlag());
        List<FileInfo> fileInfoList = fileInfoService.findListByParam(fileInfoQuery);
        List<String> delFlagFileInFolder = new ArrayList<>();
        List<String> delFlagFileIds = new ArrayList<>();
        if (fileInfoList.isEmpty()){
            return;
        }

        //得到删除的目录
        for (FileInfo fileInfo : fileInfoList) {

            if (fileInfo.getFolderType() == (FileFolderTypeEnums.FOLDER.getType())) {
                findAllFileInFolder(delFlagFileInFolder, fileInfo.getFileId(), userId,FileDelFlagEnums.USING.getFlag());
            }
                delFlagFileIds.add(fileInfo.getFileId());

        }
        if (!delFlagFileIds.isEmpty()){
            FileInfo fileInfo = new FileInfo();
            fileInfo.setDelFlag(FileDelFlagEnums.RECYCLE.getFlag());
            fileInfo.setLastUpdateTime(new Date());
            fileInfo.setRecoveryTime(new Date());
            fileInfoMapper.updateMyFileDelFlagBatch(fileInfo,delFlagFileIds,userId,FileDelFlagEnums.USING.getFlag());
        }
        if (!delFlagFileInFolder.isEmpty()){
            FileInfo fileInfo = new FileInfo();
            fileInfo.setDelFlag(FileDelFlagEnums.DEL.getFlag());
            fileInfo.setLastUpdateTime(new Date());
            fileInfo.setRecoveryTime(new Date());
            fileInfoMapper.updateMyFileDelFlagBatch(fileInfo,delFlagFileInFolder,userId,FileDelFlagEnums.USING.getFlag());
        }
    }
    public void findAllFileInFolder(List<String> fileIdList,String fileId,String userId,Integer delFlag){
        FileInfoQuery fileInfoQuery = new FileInfoQuery();
        fileInfoQuery.setFilePid(fileId);
        fileInfoQuery.setUserId(userId);
        fileInfoQuery.setDelFlag(delFlag);
//        fileInfoQuery.setFolderType(FileFolderTypeEnums.FOLDER.getType());
        List<FileInfo> fileInfoList = this.fileInfoService.findListByParam(fileInfoQuery);
        for (FileInfo fileInfo : fileInfoList) {
            if (fileInfo.getFolderType()==(FileFolderTypeEnums.FOLDER.getType())) {
                findAllFileInFolder(fileIdList, fileInfo.getFileId(), userId,delFlag);

            }
            fileIdList.add(fileInfo.getFileId());
        }
    }
    /**
     * 将根目录的文件存到hashmap中并加入缓存
     *
     * */
    public void findAllFileFolderPro(String userId){
        FileTreeNode root = new FileTreeNode();
        root.setFileId("0");
        root.setParentId("0");
        List<FileTreeNode> fileTreeNodes = new ArrayList<>();

        FileInfoQuery query = new FileInfoQuery();
        query.setUserId(userId);
        query.setStatus(FileDelFlagEnums.USING.getFlag());
        query.setFilePid("0");
//        query.setFolderType(FileFolderTypeEnums.FOLDER.getType());
        List<FileInfo> infoList = fileInfoMapper.selectList(query);
        //如果为文件 直接添加到treemap中，如果为文件夹则还需要将其子文件添加到集合中。
        for (FileInfo fileInfo : infoList) {
            FileTreeNode node = new FileTreeNode();
            node.setFileId(fileInfo.getFileId());
            node.setParentId(fileInfo.getFilePid());

            //将文件树存入内存  适用于人少项目
            if (fileInfo.getFolderType().equals(FileFolderTypeEnums.FILE.getType())){
                node.setFileInfoNode(null);
                treeMap.put(fileInfo.getFileId(),node);
            }
            if (fileInfo.getFolderType().equals(FileFolderTypeEnums.FOLDER.getType())){
                node.setFileInfoNode(new ArrayList<>());
                treeMap.put(fileInfo.getFileId(),node);
            }

            //将文件树存入缓存 适用于分布式项目
            fileTreeNodes.add(node);
            redisComponent.saveFileInfo2Cache(userId,node);
        }
        root.setFileInfoNode(fileTreeNodes);
        redisComponent.saveFileInfo2Cache(userId,root);
    }
    //修改数据时更新树
    public void loadFileInfoTree(FileInfo fileInfo,String userId){
        String filePid = fileInfo.getFilePid();
        Integer folderType = fileInfo.getFolderType();
        String fileId = fileInfo.getFileId();

        FileTreeNode node = new FileTreeNode();
        node.setFileId(fileId);
        node.setParentId(filePid);
        if (folderType.equals(FileFolderTypeEnums.FILE.getType())){
            node.setFileInfoNode(null);
        }else {
            node.setFileInfoNode(new ArrayList<>());
        }
        FileTreeNode pFileInfo = redisComponent.getFileInfo2Cache(userId, filePid);
        List<FileTreeNode> fileInfoNode = pFileInfo.getFileInfoNode();
        fileInfoNode.add(node);
        redisComponent.saveFileInfo2Cache(userId,node);
        redisComponent.saveFileInfo2Cache(userId,pFileInfo);
    }
    //查看数据时，添加缓存
    public List<FileInfo> loadData4Foler(String filePid,String userId){
        FileTreeNode cache = redisComponent.getFileInfo2Cache(userId, filePid);
        //缓存没有对应的数据
        if (cache == null){
            FileInfoQuery query = new FileInfoQuery();
            query.setFilePid(filePid);
            List<FileInfo> fileInfos = fileInfoMapper.selectList(query);

        }
        List<FileTreeNode> fileInfoNode = cache.getFileInfoNode();
        List<String> fileIdArray = new ArrayList<>();
        for (FileTreeNode fileTreeNode : fileInfoNode) {
            String fileId = fileTreeNode.getFileId();
            fileIdArray.add(fileId);
        }
        FileInfoQuery query = new FileInfoQuery();

        query.setFileIdArray(fileIdArray.toArray(new String[0]));

        return fileInfoMapper.selectList(query);
    }

    //转码
    @Async
    public void transferFile(String fileId,SessionWebUserDto webUserDto){
        Boolean transferSuccess = true;
        String targetFilePath = null;
        String cover = null;
        FileTypeEnums fileTypeEnums = null;
        FileInfo fileInfo = fileInfoMapper.selectByFileIdAndUserId(fileId,webUserDto.getUserId());
        try {
            if (fileInfo == null|| !FileStatusEnums.TRANSFER.getStatus().equals(fileInfo.getStatus())){
                return;
            }
            //临时目录
            String tempFolderName = appConfig.getProjectFolder()+Constants.FILE_FOLDER_TEMP;
            String currentUserFolderName = webUserDto.getUserId()+fileId;
            File fileFolder = new File(tempFolderName + currentUserFolderName);

            String fileSuffix = StringTools.getFileSuffix(fileInfo.getFileName());
            String month = DateUtil.format(fileInfo.getCreateTime(),DateTimePatternEnum.YYYYMM.getPattern());

            //目标目录
            String targetFolderName = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE;
            File targetFoler = new File(targetFolderName + "/" + month);
            if (!targetFoler.exists()){
                targetFoler.mkdirs();
            }
            //真实的文件名
            String realFileName = currentUserFolderName + fileSuffix;
            targetFilePath = targetFoler.getPath() + "/" + realFileName;

            //合并文件 将temp文件写入file文件
            union(fileFolder.getPath(),targetFilePath,fileInfo.getFileName(),true);

            //视频文件切割
            fileTypeEnums = FileTypeEnums.getFileTypeBySuffix(fileSuffix);
            if (fileTypeEnums == FileTypeEnums.VIDEO){
                cutFIle4Video(fileId,targetFilePath);
                //视频生成缩略图
                cover = month + "/" + currentUserFolderName + Constants.IMAGE_PNG_SUFFIX;
                String coverPath = targetFolderName + "/" + cover;
                ScaleFilter.createCover4Video(new File(targetFilePath),Constants.LENGTH_150,new File(coverPath));
            }else if(fileTypeEnums == FileTypeEnums.IMAGE){
                //生成缩略图
                cover = month + "/" + realFileName.replace(".","_.");
                String coverPath = targetFolderName+"/"+cover;
                Boolean created = ScaleFilter.createThumbnailWidthFFmpeg(new File(targetFilePath),Constants.LENGTH_150,new File(coverPath),false);
                if (!created){
                    FileUtils.copyFile(new File(targetFilePath),new File(coverPath));
                }
            }
        }catch (Exception e){
            logger.error("文件转码失败,文件ID:{},userId:{}",fileId,webUserDto.getUserId(),e);
            transferSuccess = false;
        }finally {
            FileInfo updateInfo = new FileInfo();
            updateInfo.setFileSize(new File(targetFilePath).length());
            //设置文件封面
            updateInfo.setFileCover(cover);
            updateInfo.setStatus(transferSuccess? FileStatusEnums.USING.getStatus() : FileStatusEnums.TRANSFER_FAIL.getStatus());
            //改变文件状态转码中为使用中
            fileInfoMapper.updateFileStatusWithOldStatus(fileId,webUserDto.getUserId(),updateInfo,FileStatusEnums.TRANSFER.getStatus());

        }
    }

    //视频切割
    private void cutFIle4Video(String fileId,String videoFilePath){
        //创建同名切片目录
        File tsFolder = new File(videoFilePath.substring(0,videoFilePath.lastIndexOf(".")));
        if (!tsFolder.exists()){
            tsFolder.mkdirs();
        }
//        final String CMD_TRANSFER_2TS = "ffmpeg -y -i %s  -vcodec copy -acodec copy -vbdsf h264_mp4toannexb %s";
        final String CMD_TRANSFER_2TS = "ffmpeg -y -i %s -c copy -f mpegts %s";
        final String CMD_CUT_TS = "ffmpeg -i %s -c copy -map 0 -f segment -segment_list %s -segment_time 30 %s/%s_%%4d.ts";
//        ffmpeg -i %s -c copy -f segment -segment_time 600 -segment_list out.list out%03d.ts
        String tsPath = tsFolder + "/" + Constants.TS_NAME;
        //生成.ts
        String cmd = String.format(CMD_TRANSFER_2TS,videoFilePath,tsPath);
        ProcessUtils.executeCommand(cmd,true);
        //生成索引文件.m3u8和切片.ts
        cmd = String.format(CMD_CUT_TS,tsPath,tsFolder.getPath() + "/" + Constants.M3U8_NAME,tsFolder.getPath(),fileId);
        ProcessUtils.executeCommand(cmd,true);
        //删除index.ts
        new File(tsPath).delete();
    }
    private void union(String dirPath,String toFilePath,String fileName,Boolean delSource){
        File dir = new File(dirPath);
        if (!dir.exists()){
            throw new BusinessException("目录不存在");
        }

        File[] fileList = dir.listFiles();
        File targetFile = new File(toFilePath);
        RandomAccessFile writeFile = null;
        try {
            writeFile = new RandomAccessFile(targetFile,"rw");
            byte[] b = new byte[1024*10];
            for (int i = 0;i < fileList.length;i++){
                int len = -1;
                File chunkFile = new File(dirPath+"/" + i);
                RandomAccessFile readFile = null;
                try {
                    readFile = new RandomAccessFile(chunkFile,"r");
                    while ((len = readFile.read(b)) != -1){
                        writeFile.write(b,0,len);
                    }
                }catch (Exception e){
                    logger.error("合并分片失败",e);
                    throw new BusinessException("合并分片失败");
                }finally {
                    readFile.close();
                }
            }
        }catch (Exception e){
            logger.error("合并文件：{}失败",fileName,e);
            throw new BusinessException("合并分片"+fileName+"出错了");
        }finally {
            if (writeFile != null){
                try {
                    writeFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (delSource && dir.exists()){
                try {
                    FileUtils.deleteDirectory(dir);
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    //重命名
    private String autoRename(String filePid, String userId, String fileName) {
        FileInfoQuery fileInfoQuery = new FileInfoQuery();
        fileInfoQuery.setUserId(userId);
        fileInfoQuery.setFilePid(filePid);
        fileInfoQuery.setDelFlag(FileDelFlagEnums.USING.getFlag());
        fileInfoQuery.setFileName(fileName);
        Integer count = this.fileInfoMapper.selectCount(fileInfoQuery);
        if (count > 0) {
            return StringTools.rename(fileName);
        }

        return fileName;
    }
    private void updateUserSpace(SessionWebUserDto webUserDto, Long useSpace) {
        Integer count = userInfoMapper.updateUserSpace(webUserDto.getUserId(), useSpace, null);
        if (count == 0) {
            throw new BusinessException(ResponseCodeEnum.CODE_904);
        }
        UserSpaceDto spaceDto = redisComponent.getUserSpaceUse(webUserDto.getUserId());
        spaceDto.setUseSpace(spaceDto.getUseSpace() + useSpace);
        redisComponent.saveUserSpace(webUserDto.getUserId(), spaceDto);
    }

//    private List<>

    @Override
    public void loadDataList(String userId, String fileId) {
        loadData4Foler(fileId,userId);

    }
}